package xyz.naokeziteng.level2cache.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import xyz.naokeziteng.level2cache.annotations.Level2CachePut;
import xyz.naokeziteng.level2cache.service.L1CacheService;
import xyz.naokeziteng.level2cache.service.L2CacheService;
import xyz.naokeziteng.level2cache.util.SpringELUtils;

import java.lang.reflect.Method;

/**
 * @author hawk
 * @date 2022/8/2
 * @desc 缓存更新切面
 **/
@Slf4j
@Aspect
@Component
public class CachePutAspect {
    @Autowired
    private L1CacheService l1CacheService;
    @Autowired
    private L2CacheService l2CacheService;

    @Pointcut("@annotation(xyz.naokeziteng.level2cache.annotations.Level2CachePut)")
    public void cachePut() {
    }

    @Around("cachePut()")
    public Object aroundCachePut(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        try {
            Level2CachePut cachePut = method.getAnnotation(Level2CachePut.class);
            //获取缓存完整key
            String key = SpringELUtils.parseExpression(cachePut.key(), method, joinPoint.getArgs());
            String completeKey = cachePut.cacheName() + ":" + key;
            log.debug("缓存更新，开始查询数据库");
            Object result = joinPoint.proceed();
            log.debug("l2缓存更新");
            l2CacheService.set(completeKey, result, cachePut.l2Timeout());
            log.debug("l1缓存更新");
            l1CacheService.cacheUpdate(completeKey);
            return result;
        } catch (Exception e) {
            log.error("缓存更新失败, {}", e.getMessage());
            throw new RuntimeException("缓存更新失败, " + e.getMessage());
        }
    }

}
